# _*_ coding:utf-8 _*_

'''
通过角本生成python程序中的通用功能函数集
'''

import numpy as np
import logging
import sys
import ast

def stateY(_src, y):
    _src.statusY[y] = 1


def stateKeyY(_src, key, nparr_data='', nparr_extdata='', nparr_moredata=''):
    # 如果为空，也占一行，世界上，每个不确定都是不同的
    if (key == None):
        # 生成的Key中引用子任务id，否则在并发计算时，List表怎么做合并？列索引重复了。
        # 格式：_N_0__numY
        key = '_N_' + _src.subTaskId + '__' + str(_src.numY + 1)

    y = _src.dictY.get(key, -1)
    if (y < 0):
        if (_src.numY < _src.Max_numY):
            y = _src.numY
            _src.dictY[key] = y
            _src.numY += 1

            # 这里取SR缺省action，纯是为了辅助决定后面的初始化数据类型
            action = _src.get_value('action', '')
            dtype = float
            try:
                if isinstance(eval(action), int):
                    dtype=int
            except:
                pass

            arr_ = [0] * _src.numX
            nparr_ = np.array([arr_], dtype=dtype)
            if (nparr_data == ''):
                # 如果data没有初始值，extdata、moredata也不应有初始值
                _src.data = np.r_[_src.data, nparr_]
                _src.extdata = np.r_[_src.extdata, nparr_]
                nparr_ = np.zeros([1, _src.numX], dtype='object')
                for i in range(_src.numX):
                    nparr_[0, i] = []
                _src.moredata = np.r_[_src.moredata, nparr_]
            else:
                _src.data = np.r_[_src.data, [nparr_data]]

                if (nparr_extdata == ''):
                    _src.extdata = np.r_[_src.extdata, nparr_]
                else:
                    _src.extdata = np.r_[_src.extdata, [nparr_extdata]]

                if (len(nparr_moredata) <= 0):
                    nparr_ = np.zeros([1, _src.numX], dtype='object')
                    for i in range(_src.numX):
                        nparr_[0, i] = []
                    _src.moredata = np.r_[_src.moredata, nparr_]
                else:
                    _src.moredata = np.r_[_src.moredata, [nparr_moredata]]

            _src.statusY = [0] * _src.numY
    _src.statusY[y] = 1


def actionX(_src, x, val):
    _src.data[_src.curY, x] += val


def actionExtX(_src, x, val):
    #_src.getCurExtdata(x)[0] += val
    _src.extdata[_src.curY, x] += val


def actionMoreX(_src, x, val):
    #_src.getCurMoredata(x)[0].append(val)
    _src.moredata[_src.curY, x].append(val)


def reset(_src):
    # 对一个数组来说，在内存空间已经开好，直接对每一个元素赋值的方法初始化效率更高
    #_src.statusY = [False] * _src.numY
    _src_statusY = _src.statusY
    for i in range(_src.numY):
        _src_statusY[i] = 0


def getResult(_src):
    return _src.data, _src.extdata, _src.moredata


def getTitles(_src):
    return str(_src.titlesY) + '\n' + str(_src.titlesX)


def getLogger(log='StatisticsReporter', filename=''):
    '''
    DEBUG       细节信息，仅当诊断问题时适用。
    INFO        确认程序按预期运行
    WARNING     表明有已经或即将发生的意外（例如：磁盘空间不足）。程序仍按预期进行
    ERROR       由于严重的问题，程序的某些功能已经不能正常执行
    CRITICAL    严重的错误，表明程序已不能继续执行
    :param log:
    :param filename:
    :return:
    '''
    logger = logging.getLogger(log)
    if not logger.handlers:
        logger.setLevel(logging.INFO)

        ch = logging.StreamHandler()
        ch.setLevel(logging.DEBUG)

        formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
        ch.setFormatter(formatter)
        logger.addHandler(ch)

        if filename:
            fh = logging.FileHandler(filename)
            fh.setLevel(logging.CRITICAL)
            fh.setFormatter(formatter)
            logger.addHandler(fh)

    return logger


def sgfun(data, extdata):
    #data += extdata
    pass


def call_sgfun(_src, sgfun=sgfun):
    data = _src.data
    extdata = _src.extdata

    for i in range(_src.numY):
        for j in range(_src.numX):
            data[i,j] = sgfun(data[i,j], extdata[i,j])


def getDict(key, dict_, default=''):
    '''
    dict_.get(key, default))    #这种方式无法处理dict_为空等异常情况
    '''
    try:
        return dict_[key]
    except:
        return default


def getDictPos(key, startpos, dict_):
    try:
        return dict_[key] + startpos
    except:
        return -1


def sortKeysList(key='', startpos=0, keys=[]):
    if not key:
        keys = sorted(keys)
        return keys

    if isinstance(keys[0], str):
        last = ''
    else:
        last = -sys.float_info.max-1

    for i in range(len(keys)):
        if (keys[i] >= key > last):
            return i + startpos
        last = keys[i]

    return -1


def tryExpr(expr='', devVal=None):
    '''
    当你想对一个变量计算，又担心它是None，可以用这个函数包装一下
    '''
    try:
        return eval(expr, self.py_module.__dict__)
    except:
        return devVal


def tryLeval(expr='', defVal=0):
    '''
    eval函数的安全替换品ast.literal_eval
    '''
    try:
        return ast.literal_eval(expr)
    except:
        return defVal


def getMark(_src, markName):
    if markName:
        return _src.markit.get(markName, None)
    else:
        return (_src.numY, _src.numX)


def sqlFetchall(_src, sql, params=None):
    if _src.conn:
        cursor = _src.conn.cursor()
        cursor.execute(sql, params)
        results = cursor.fetchall()
        cursor.close()
        return results
    return {}


if __name__ == '__main__':
    list_ = sortKeysList(keys=[1,3,8,12,19], keyName='key', key='')
    print (sortKeysList(list_, key=12))
